package org.op.service.doc;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import javax.swing.text.AttributeSet;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Document;
import javax.swing.text.StyledDocument;

import org.op.service.wwcache.WikiwordCacheService;

public class StyledDocumentConversionServiceImpl implements DocumentConversionService {

	private static final Object SPACE_DEMARKATION = "@$%#";
	private StyleSets styleSets;  // injected
	private WikiwordCacheService wwService;
	
	private AttributeSet contentSet;
	private AttributeSet linkSet;
	
	public List<String> documentToText(Document document) throws Exception {
		String text = document.getText(0, document.getLength());
		return textToList(text);
	}
	
	/**
	 *   Converts plain text into a list of strings 
	 *   
	 * @param text
	 * @return
	 */
	public List<String> textToList(String text) {
		List<String> content = new ArrayList<String>();
		BufferedReader in = null;
		try {
			StringReader reader = new StringReader(text);
			in = new BufferedReader(reader);
	        String str;
	        while ((str = in.readLine()) != null) {
	            content.add(str);
	        }
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (in!=null) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return content;
	}

	public Document textToDocument(List<String> content) throws Exception {
        
		styleSets.init(); // reinitialize -- the fonts may have changed
		
		contentSet = styleSets.getSet(StyleSets.CONTENT_SET);
		linkSet = styleSets.getSet(StyleSets.HTML_SET);
		
        StyledDocument doc = new DefaultStyledDocument();
        // set the default style
        doc.setParagraphAttributes(0, 0, contentSet, true);
        
        //StyledDocument doc = new HTMLDocument();
		for (String line : content) {
			insertLineIntoDocument(doc, line, doc.getLength());
			
			// The system newline adds an extra character to the end of the document line.  Use a \n instead.  May not be consistent across OS's
			//String newline = System.getProperty("line.separator");
			String newline = "\n";

			// add a newline at the end
			doc.insertString(doc.getLength(), newline, contentSet);
		}
		
		return doc;
	}

	public Document insertLineIntoDocument(Document doc, String line, int insertionPoint) throws Exception  {
		        
		// before loading, find all instances of multiple spaces,
		//  which would normally be stripped by the tokenizer
		line = demarkMultispaces(line);
		
		StringTokenizer st = new StringTokenizer(line, " ");  // parse out all of the words in this string
		String word = null;
		String appender = null;
		while (st.hasMoreTokens()) {
			word = st.nextToken();
			appender = null;
						
			if (!word.equals(SPACE_DEMARKATION)) {
				int wordLen = word.length();
				// check to see if word ends with a punctuation
				Character c = word.charAt(wordLen-1);
				if (!Character.isLetter(c)) {
					appender = c.toString();
					word = word.substring(0,wordLen-1);
				}
				wordLen = word.length();
				
				if (isWikiWord(word)) {
					doc.insertString(insertionPoint, word, linkSet);
				} else {
					doc.insertString(insertionPoint, word, contentSet);
				}
				insertionPoint += wordLen;
				
				if (appender!=null) {
					// handle punctuation
					doc.insertString(insertionPoint, appender, contentSet);
					insertionPoint += appender.length();
				}
			}
			
			// add a single space between words
			if (st.hasMoreTokens()) {
				doc.insertString(insertionPoint, " ", contentSet);
				insertionPoint += 1;
			}
		}
		
		// restore default style
		((StyledDocument)doc).setParagraphAttributes(insertionPoint, 0, contentSet, true);	
		//doc.insertString(doc.getLength(), "", contentSet);
		
		return doc;
	}

	/**
	 *  This is a way of marking-up multispaces 
	 *  so that they are not consumed by the StringTokenizer
	 * 
	 * @param line
	 * @return
	 */
	private String demarkMultispaces(String line) {
		
		int dblSpace = line.indexOf("  ");
		while (dblSpace>=0){
			StringBuffer newln = new StringBuffer(line.substring(0, dblSpace ));
			newln.append(" ");
			
			line = line.substring(dblSpace+1);
			while (line.length()>0 && line.charAt(0)== ' ') {
				newln.append(SPACE_DEMARKATION);
				newln.append(" ");
				line = line.substring(1);
			}
			newln.append(line);
			
			line = newln.toString();
			dblSpace = line.indexOf("  ");
		}
		
		return line;
	}

	private boolean isWikiWord(String word) {
		boolean ww = wwService.getAliasMap().containsKey(word);
		return ww;
	}

	public StyleSets getStyleSets() {
		return styleSets;
	}

	public void setStyleSets(StyleSets styleSets) {
		this.styleSets = styleSets;
	}
	
	public WikiwordCacheService getWwService() {
		return wwService;
	}

	public void setWwService(WikiwordCacheService wwService) {
		this.wwService = wwService;
	}

	public static void main (String[] args) {
		
		String text = "Now  is the   time for a sofa king to appear.";
		StyledDocumentConversionServiceImpl impl = new StyledDocumentConversionServiceImpl();
		text = impl.demarkMultispaces(text);
		
		System.out.println("new text is " + text);

		
	}

}
